//
//  QueueDictionary.m
//  Portal
//
//  Created by JingXing Wu on 12-3-13.
//  Copyright (c) 2012年 GuangZhouXuanWu. All rights reserved.
//

#import "XMSQueueDictionary.h"

@implementation XMSQueueDictionary
{
    NSMutableArray *_arQueue;
    
    Class _storeCls;
}

@synthesize arQueue = _arQueue;
@synthesize storeCls = _storeCls;

- (id)init
{
    return [self initWithStoreClass:[XMSKvPair class]];
}

- (id)initWithStoreClass:(Class)cls
{
    self=[super init];

    _arQueue = [NSMutableArray new];

    _storeCls = cls;

    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    XMSQueueDictionary *qd = [[XMSQueueDictionary alloc]initWithStoreClass:self.storeCls];
    [qd addKvPairFromOtherQueueDictionaryDirect:self];
    return qd;
}

- (void)addKvPairDirectFromArray:(NSArray *)arPair
{
    [_arQueue addObjectsFromArray:arPair];
}

- (void)addKvPairDirect:(XMSKvPair *)kv
{
    [_arQueue addObject:kv];
}

- (void)addKey:(id)key value:(id)value
{
    XMSKvPair *pair = [[_storeCls new] autorelease_mm];
    pair.idKey = key;
    pair.idValue = value;
    [self addKvPairDirect:pair];
}

- (void)insertKvPair:(XMSKvPair *)kv directAtIndex:(NSUInteger)nIndex
{
    [_arQueue insertObject:kv atIndex:nIndex];
}

- (void)addKvPair:(XMSKvPair *)kv
{
    [self addKvPair:kv compareKey:^BOOL(id comparekey)
    {
        return [comparekey compare:kv.idKey ] == NSOrderedSame;
    }];
}

- (void)addKvPair:(XMSKvPair *)kv compareKey:(BOOL(^)(id comparekey))compare
{
    NSUInteger nIndex = [self indexOfKey:kv.idKey compareKey:compare];
    if (nIndex == NSNotFound)
        [_arQueue addObject:kv];
    else
        [_arQueue replaceObjectAtIndex:nIndex withObject:kv];
}

- (void)addKvPairFromOtherQueueDictionary:(XMSQueueDictionary *)qd
{
    for (NSInteger i = 0; i < [qd count]; i++)
    {
        [self addKvPairFromOtherQueueDictionary:qd compareKey:^BOOL(id comparekey1, id comparekey2)
        {
            return [comparekey1 compare:comparekey2] == NSOrderedSame;
        }];
    }
}

- (void)addKvPairFromOtherQueueDictionary:(XMSQueueDictionary *)qd compareKey:(BOOL(^)(id comparekey1, id comparekey2))compare
{
    for (NSInteger i = 0; i < [qd count]; i++)
    {
        XMSKvPair *kv = [qd kvPairAtIndex:i];
        [self addKvPair:kv compareKey:^BOOL(id comparekey)
        {
            return compare(comparekey, kv.idKey );
        }];
    }
}

- (void)addKvPairFromOtherQueueDictionaryDirect:(XMSQueueDictionary *)qd
{
    [_arQueue addObjectsFromArray:qd.arQueue];
}

- (void)addKvPairFromDictionary:(NSDictionary *)dic
{
    NSArray *arKey = [dic allKeys];
    for (NSString *s in arKey)
        [self setValue:[dic objectForKey:s] forKey:s];
}

- (NSMutableDictionary *)toNSDictionary
{
    if (_arQueue.count > 0)
    {
        XMSKvPair *kv = [_arQueue objectAtIndex:0];
        if ([kv.idKey isKindOfClass:[NSString class]] == YES)
        {
            NSMutableDictionary *dic = [[NSMutableDictionary new] autorelease_mm];
            for (XMSKvPair *kv in _arQueue)
            {
                [dic setObject:kv.idValue forKey:kv.idKey ];
            }
            return dic;
        }
        return nil;
    }
    return [[NSMutableDictionary new] autorelease_mm];
}

- (NSUInteger)indexOfKey:(id)key
{
    return [self indexOfKey:key compareKey:^BOOL(id comparekey)
    {
        return [comparekey compare:key] == NSOrderedSame;
    }];
}

- (NSUInteger)indexOfKey:(id)key compareKey:(BOOL(^)(id comparekey))compare
{
    for (NSUInteger i = 0; i < _arQueue.count; i++)
    {
        XMSKvPair *kv = [_arQueue objectAtIndex:i];
        if (compare(kv.idKey ) == YES)
            return i;
    }
    return NSNotFound;
}

- (XMSKvPair *)kvPairAtLast
{
    return [self kvPairAtIndex:[self count] - 1];
}

- (XMSKvPair *)kvPairAtKey:(id)key
{
    return [self kvPairAtKey:key compareKey:^BOOL(id comparekey)
    {
        return [comparekey compare:key] == NSOrderedSame;
    }];
}

- (XMSKvPair *)kvPairAtKey:(id)key compareKey:(BOOL(^)(id comparekey))compare
{
    for (XMSKvPair *kv in _arQueue)
    {
        if (compare(kv.idKey ) == YES)
            return kv;
    }
    return nil;
}

- (XMSKvPair *)kvPairAtIndex:(NSUInteger)nIndex
{
    return (XMSKvPair *) [_arQueue objectAtIndex:nIndex];
}

- (void)setValue:(id)value atIndex:(NSUInteger)nIndex
{
    XMSKvPair *pair = [_arQueue objectAtIndex:nIndex];
    pair.idValue = value;
}

- (void)setValue:(id)value forKey:(id)key
{
//    NSInteger i=0;
//    for(;i<_arQueue.count;i++)
//    {
//        CQDKv* kv=[_arQueue objectAtIndex:i];
//        if([kv.idKey compare:key]==NSOrderedSame)
//        {
//            kv.idValue=value;
//            return;
//        }
//    }
//    if(i>=_arQueue.count)
//    {
//        CQDKv* kv=[[CQDKv new]autorelease];
//        kv.idKey =key;
//        kv.idValue=value;
//        [_arQueue addObject:kv];
//    }
    [self setValue:value forKey:key compareKey:^BOOL(id comparekey)
    {
        return [comparekey compare:key] == NSOrderedSame;
    }];
}

- (id)keyAtLast
{
    return [self kvPairAtLast].idKey ;
}

- (id)valueAtLast
{
    return [self kvPairAtLast].idValue;
}

- (id)getValueForKey:(id)key
{
    id value = nil;
    for (NSInteger i = 0; i < _arQueue.count; i++)
    {
        XMSKvPair *kv = [_arQueue objectAtIndex:i];
        if ([kv.idKey compare:key] == NSOrderedSame)
        {
            value = kv.idValue;
            break;
        }
    }
    return value;
}

- (id)getValueForIndex:(NSUInteger)nIndex
{
    return ((XMSKvPair *) [_arQueue objectAtIndex:nIndex]).idValue;
}

- (id)getKeyForIndex:(NSUInteger)nIndex
{
    return ((XMSKvPair *) [_arQueue objectAtIndex:nIndex]).idKey ;
}

- (id)getKeyForCompareKey:(BOOL(^)(id key))compare
{
    __block id key=nil;
    [_arQueue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        id k = ((XMSKvPair*)obj).idKey;
        BOOL bResult = compare(k);
        if(bResult == YES)
        {
            key = k;
            *stop =YES;
        }
    }];
    return key;
}

- (id)getValueForKey:(id)key value:(id(^)())value
{
    id v = [self getValueForKey:key];
    if (v == nil)
    {
        v = value();
        [self setValue:v forKey:key];
    }
    return v;
}

- (id)getValueForCompareKey:(BOOL(^)(id key))compare
{
    BOOL b = NO;
    NSInteger i = NSNotFound;
    for (NSInteger j = 0; j < _arQueue.count; j++)
    {
        id key = [self getKeyForIndex:j];
        b = compare(key);
        if (b == YES)
        {
            i = j;
            break;
        }
    }
    return i != NSNotFound ? [self getValueForIndex:i] : nil;
}

- (id)getValueForKey:(id)key compareKey:(BOOL(^)(id key))compare value:(id(^)())value
{
    id v = [self getValueForCompareKey:compare];
    if (v == nil)
    {
        v = value();
        [self setValue:v forKey:key compareKey:compare];
    }
    return v;
}

- (void)setValue:(id)value forKey:(id)key compareKey:(BOOL(^)(id comparekey))compare
{
//    int i=0;
//    for(;i<_arQueue.count;i++)
//    {
//        CQDKv* kv=[_arQueue objectAtIndex:i];
//        BOOL b=compare(kv.idKey );
//        if(b==YES)
//        {
//            kv.idValue=value;
//            return;
//        }
//    }
//    if(i>=_arQueue.count)
//    {
//        CQDKv* kv=[[CQDKv new]autorelease];
//        kv.idKey =key;
//        kv.idValue=value;
//        [_arQueue addObject:kv];
//    }
    [self setValue:^id
    {
        return value;
    }          Key:key compareKey:compare];
}

- (void)setValue:(id(^)())value Key:(id)key compareKey:(BOOL(^)(id comparekey))compare
{
    if (key == nil)
        return;
    NSUInteger i = 0;
    for (; i < _arQueue.count; i++)
    {
        XMSKvPair *kv = [_arQueue objectAtIndex:i];
        BOOL b = compare(kv.idKey );
        if (b == YES)
        {
            id v = value();
            if (v != nil)
                kv.idValue = v;
            return;
        }
    }
    if (i >= _arQueue.count)
    {
        id v = value();
        if (v != nil)
        {
            XMSKvPair *kv = [[_storeCls new] autorelease_mm];
            kv.idKey = key;
            kv.idValue = v;
            [_arQueue addObject:kv];
        }
    }
}

- (void)sort:(BOOL)ascending
{
    NSArray *ar = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"m_value" ascending:ascending]];
    [_arQueue sortUsingDescriptors:ar];
}

- (NSUInteger)count
{
    return _arQueue.count;
}

- (NSMutableArray *)allKeys
{
    NSMutableArray *ar = [[[NSMutableArray alloc] initWithCapacity:_arQueue.count] autorelease_mm];
    for (XMSKvPair *kv in _arQueue)
        [ar addObject:kv.idKey ];
    return ar;
}

- (NSMutableArray *)allValues
{
    NSMutableArray *ar = [[[NSMutableArray alloc] initWithCapacity:_arQueue.count] autorelease_mm];
    for (XMSKvPair *kv in _arQueue)
        [ar addObject:kv.idValue];
    return ar;
}

- (void)replaceKey:(NSUInteger)nIndex Key:(id)key
{
    XMSKvPair *kv = [_arQueue objectAtIndex:nIndex];
    kv.idKey = key;
}

//-(void)ReplaceKey:(id)oldkey newkey:(id)newkey
//{
//    int nIndex=[_arQueue indexOfObject:oldkey];
//    if(nIndex>=0&&nIndex<_arQueue.count)
//        [self ReplaceKey:nIndex key:newkey];
//}

- (void)removeAllObjects
{
    [_arQueue removeAllObjects];
}

- (void)removeObjectsInRange:(NSRange)range
{
    [_arQueue removeObjectsInRange:range];
}

- (void)removeObjects:(NSArray *)arObj
{
    [_arQueue removeObjectsInArray:arObj];
}

- (void)removeObject:(XMSKvPair *)kv
{
    [_arQueue removeObject:kv];
}

- (void)removeObjectAtIndex:(NSUInteger)nIndex
{
    [_arQueue removeObjectAtIndex:nIndex];
}

- (void)removeObjectForKey:(id)key
{
    [self removeObjectForKey:key compare:^BOOL(id comparekey)
    {
        return [comparekey compare:key] == NSOrderedSame;
    }];
}

- (void)removeObjectForKey:(id)key compare:(BOOL(^)(id comparekey))compare
{
    for (NSUInteger i = 0; i < _arQueue.count; i++)
    {
        XMSKvPair *pair = [_arQueue objectAtIndex:i];
        if (compare(pair.idKey ) == YES)
        {
            [self removeObjectAtIndex:i];
            break;
        }
    }
}

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
{
    [_arQueue enumerateObjectsUsingBlock:block];
}

- (void)enumerateKeyValuesUsingBlock:(void (^)(id key, id value, NSUInteger idx, BOOL *stop))block
{
    [_arQueue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        XMSKvPair *kv = obj;
        block(kv.idKey,kv.idValue,idx,stop);
    }];
}

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len
{
    return [_arQueue countByEnumeratingWithState:state objects:buffer count:len];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"%@,\r\n%ud,\r\n%@", [super description], ToUInt _arQueue.count, [_arQueue description]];
}

- (void)dealloc
{
    [_arQueue release_mm];
    superdealloc_mm;
}

@end


@implementation XMSQueueDictionary (NSMutableArrayValue)

- (NSMutableArray *)value:(id)value
{
    return (NSMutableArray *) value;
}

- (NSMutableArray *)addArrayValueWithkey:(id)key
{
    NSMutableArray *ar = [[NSMutableArray new] autorelease_mm];
    [self addKey:key value:ar];
    return ar;
}

- (NSMutableArray *)addArrayValueWithSetKey:(id)key
{
    return [self getValueForKey:key value:^id
    {
        return [[NSMutableArray new]autorelease_mm];
    }];
}

- (NSMutableArray *)insertArrayValueWithkey:(id)key atIndex:(NSUInteger)nIndex
{
    NSMutableArray *ar = [[NSMutableArray new] autorelease_mm];
    [self insertKvPair:[XMSKvPair kvPairWithKey:key value:ar] directAtIndex:nIndex];
    return ar;
}

- (void)enumerateArrayValueUsingBlock:(void (^)(id key, id obj, NSUInteger idx, BOOL *stop))block
{
    [_arQueue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        __block BOOL bThisstop = NO;
        XMSKvPair *pair = (XMSKvPair *) obj;
        if ([pair.idValue isKindOfClass:[NSArray class]])
        {
            [(NSArray *) pair.idValue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
            {
                block(pair.idKey , obj, idx, stop);
                bThisstop = *stop;
            }];
        }
        *stop = bThisstop;
    }];
}

- (void)enumerateObjectUsingBlockFromBegin:(void (^)(id key, id obj, NSUInteger idx1, NSUInteger idx2, BOOL *stop))block
{
    __block BOOL bThisstop = NO;
    for (NSUInteger i = 0; i < [self count]; i++)
    {
        XMSKvPair *pair = [self kvPairAtIndex:i];
        NSUInteger nCount = [self value:pair.idValue].count;
        if(nCount>0)
        {
            for (NSUInteger j = 0; j < [self value:pair.idValue].count; j++)
            {
                block(pair.idKey , [[self value:pair.idValue] objectAtIndex:j], i, j, &bThisstop);
                if (bThisstop == YES)
                    break;
            }
        }
        else
            block(pair.idKey , nil, i, NSNotFound, &bThisstop);
        if (bThisstop == YES)
            break;
    }
}

- (void)enumerateObjectUsingBlockFromEnd:(void (^)(id key, id obj, NSUInteger idx1, NSUInteger idx2, BOOL *stop))block
{
    __block BOOL bThisstop = NO;
    for (NSInteger i = [self count] - 1; i >= 0; i--)
    {
        XMSKvPair *pair = [self kvPairAtIndex:i];
        NSUInteger nCount = [self value:pair.idValue].count;
        if(nCount>0)
        {
            for (NSInteger j = nCount - 1; j >= 0; j--)
            {
                block(pair.idKey , [[self value:pair.idValue] objectAtIndex:j], i, j, &bThisstop);
                if (bThisstop == YES)
                    break;
            }
        }
        else
            block(pair.idKey , nil, i, NSNotFound, &bThisstop);
        if (bThisstop == YES)
            break;
    }
}

- (NSUInteger)totalCount
{
    __block NSUInteger nCount = 0;
    [_arQueue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        XMSKvPair *pair = (XMSKvPair *) obj;

        nCount++;
        nCount += [self value:pair.idValue].count;
    }];
    return nCount;
}

- (id)valueAtKeyArrayIndex:(NSUInteger)nIndex1 valueArrayIndex:(NSUInteger)nIndex2
{
    XMSKvPair *pair = [self kvPairAtIndex:nIndex1];
    return [[self value:pair.idValue] objectAtIndex:nIndex2];
}

- (id)objectAtLast
{
    XMSKvPair *pair = [self kvPairAtIndex:[self count] - 1];
    if ([self value:pair.idValue].count > 0)
        return [[self value:pair.idValue] objectAtIndex:[self value:pair.idValue].count - 1];
    return pair.idKey ;
}

- (NSMutableArray*)arrayValueAtIndex:(NSUInteger)nIndex
{
    return [self kvPairAtIndex:nIndex].idValue;
}

- (NSMutableArray*)allArrayValue
{
    NSMutableArray * ar = [[NSMutableArray new] autorelease_mm];
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        [ar addObjectsFromArray:(((XMSKvPair*)obj).idValue)];
    }];
    return ar;
}

- (NSString *)descriptionWithSpace:(NSString *)space
{
    NSMutableString *description = [NSMutableString stringWithFormat:@"\n%@{", space];
    for (id obj in _arQueue)
    {
        [description appendFormat:@"%@", [obj descriptionWithSpace:[space stringByAppendingString:@"    "]]];
    }
    [description appendFormat:@"\n%@}", space];
    
    return description;
}

- (NSString *)description
{
    return [self descriptionWithSpace:@""];
}

@end